package com.card.hwatt.controllers;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.commons.lang.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.card.hwatt.assembler.CardAssembler;
import com.card.hwatt.assembler.CardRecordAssembler;
import com.card.hwatt.assembler.CompanyAssembler;
import com.card.hwatt.assembler.EmployeeAssembler;
import com.card.hwatt.assembler.HolidayAssembler;
import com.card.hwatt.assembler.MonthSumAssembler;
import com.card.hwatt.assembler.MonthWorkAssembler;
import com.card.hwatt.assembler.ScheduleAssembler;
import com.card.hwatt.dto.*;
import com.card.hwatt.service.CardService;
import com.card.hwatt.service.DepartmentService;
import com.card.hwatt.service.EmployeeService;
import com.card.hwatt.service.HolidayService;
import com.card.hwatt.service.ScheduleService;

/**
 * 考勤汇总
 * @author Administrator
 *
 */
@Controller
@Scope("prototype")
@RequestMapping("/monthsum")
public class MonthSumController extends BaseController {

	@Autowired
	@Qualifier("employeeService")
	private EmployeeService employeeService;

	@Autowired
	@Qualifier("cardService")
	private CardService cardService;

	@Autowired
	@Qualifier("holidayService")
	private HolidayService holidayService;

	@Autowired
	@Qualifier("scheduleService")
	private ScheduleService scheduleService;

	@Autowired
	@Qualifier("departmentService")
	private DepartmentService departmentService;

	@RequestMapping("/index")
	public String index() {
		return "monthsum";
	}

	protected Company loadCompany(Long id) {
		List<Object> params = new ArrayList<Object>();
		params.add(id);
		List<Company> companyList = CompanyAssembler.convert(departmentService
				.loadAll(new PageParam(0, 0, " id = ? and id != 2 ", params,
						" orderBy asc "))).rows;
		if (companyList.size() == 0) {
			return null;
		}
		Company company = companyList.get(0);
		return company;
	}

	@RequestMapping(value = "/print")
	public void print(HttpServletRequest request, HttpServletResponse response,
			Long id, int year, int month) {

		if (id == null) {
			return;
		}
		Company company = loadCompany(id);
		if (company == null) {
			return;
		}

		Calendar calendar = Calendar.getInstance();
		calendar.set(year, month - 1, 1, 0, 0, 0);

		List<Employee> employees = loadEmployee(id);
		List<Card> cards = loadCard(id, year, month);

		Schedule schedule = ScheduleAssembler.convert(scheduleService.get(
				String.format("%d-%d-01", year, month), id));

		List<Holiday> holidaies = loadHoliday(year, month);

		Calendar end = Calendar.getInstance();
		end.set(year, month - 1, 1, 0, 0, 0);
		end.add(Calendar.MONTH, 1);
		List<CardRecord> list = CardRecordAssembler.convert(employees, cards,
				schedule, DateFormatUtils.format(end, "yyyy-MM-dd"));
		int quantity = list.size();

		Map<String, Object> map = MonthWorkAssembler.convert(employees, list,
				new ArrayList<Leave>(), holidaies, schedule);

		MonthWork[] footers = ((MonthWork[]) map.get("footer"));
		MonthWork footer = footers[footers.length - 1];
		MonthSum result = MonthSumAssembler.convert(footer, company.quantity,
				calendar.getMaximum(Calendar.DAY_OF_MONTH) - holidaies.size(),
				quantity);

		Map<String, Object> params = new HashMap<String, Object>();
		params.put("year", year);
		params.put("month", month);
		params.put("title", company.departmentName + year + "年" + month
				+ "月电子考勤统计表");
		HttpSession session = request.getSession();
		Object user = session.getAttribute("user");
		params.put("name", user == null ? StringUtils.EMPTY : "打印人：" + user);
		params.put("date",
				"打印日期：" + DateFormatUtils.format(new Date(), "yyyy-MM-dd"));

		List<MonthSum> rows = new ArrayList<MonthSum>();
		rows.add(result);
		this.print(request, response, "monthsum", rows, params);
	}

	@RequestMapping("/load")
	public @ResponseBody
	MonthSum load(Long id, int year, int month) {

		if (id == null) {
			return new MonthSum();
		}
		Company company = loadCompany(id);
		if (company == null) {
			return new MonthSum();
		}

		Calendar calendar = Calendar.getInstance();
		calendar.set(year, month - 1, 1, 0, 0, 0);

		List<Employee> employees = loadEmployee(id);
		List<Card> cards = loadCard(id, year, month);

		Schedule schedule = ScheduleAssembler.convert(scheduleService.get(
				String.format("%d-%d-01", year, month), id));

		List<Holiday> holidaies = loadHoliday(year, month);

		Calendar end = Calendar.getInstance();
		end.set(year, month - 1, 1, 0, 0, 0);
		end.add(Calendar.MONTH, 1);
		List<CardRecord> list = CardRecordAssembler.convert(employees, cards,
				schedule, DateFormatUtils.format(end, "yyyy-MM-dd"));
		int quantity = list.size();
		Map<String, Object> map = MonthWorkAssembler.convert(employees, list,
				new ArrayList<Leave>(), holidaies, schedule);

		MonthWork[] footers = ((MonthWork[]) map.get("footer"));
		MonthWork footer = footers[footers.length - 1];
		MonthSum result = MonthSumAssembler.convert(footer, company.quantity,
				calendar.getMaximum(Calendar.DAY_OF_MONTH) - holidaies.size(),
				quantity);
		return result;
	}

	private List<Holiday> loadHoliday(Integer year, Integer month) {
		if (year == null || month == null) {
			return new ArrayList<Holiday>();
		}

		String[] parsePatterns = new String[] { "yyyy-M-dd" };
		Date startDate = null;
		try {
			startDate = DateUtils.parseDate(String.format("%d-%d-01",
					year.intValue(), month.intValue()), parsePatterns);
		} catch (Exception e) {
			startDate = new Date();
		}
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(startDate);
		calendar.add(Calendar.MONTH, 1);

		Date endDate = calendar.getTime();

		List<Object> params = new ArrayList<Object>();

		String pattern = "yyyyMMdd";
		params.add(DateFormatUtils.format(startDate, pattern));
		params.add(DateFormatUtils.format(endDate, pattern));

		List<Holiday> result = HolidayAssembler.convert(holidayService
				.loadAll(new PageParam(0, 0, " id >= ? and id < ? ", params,
						" id desc ")).rows);
		return result;
	}

	private List<Card> loadCard(Long id, Integer year, Integer month) {

		if (year == null || month == null) {
			return new ArrayList<Card>();
		}

		String[] parsePatterns = new String[] { "yyyy-M-dd HH:mm:ss" };
		Date startDate = null;
		try {
			startDate = DateUtils.parseDate(
					String.format("%d-%d-01 00:00:00", year.intValue(),
							month.intValue()), parsePatterns);
		} catch (Exception e) {
			startDate = new Date();
		}
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(startDate);
		calendar.add(Calendar.MONTH, 1);
		calendar.add(Calendar.DATE, 1);
		Date endDate = calendar.getTime();

		List<Object> params = new ArrayList<Object>();
		params.add("%@" + id + "@%");
		params.add(new java.sql.Date(startDate.getTime()));
		params.add(new java.sql.Date(endDate.getTime()));

		List<Card> result = CardAssembler
				.convert(cardService
						.loadAll(new PageParam(
								0,
								0,
								" employee.department.path like ? and date >= ? and date < ? ",
								params, " date asc ")).rows);

		return result;
	}

	private List<Employee> loadEmployee(Long id) {
		List<Object> params = new ArrayList<Object>();

		params.add("%@" + id + "@%");

		List<Employee> result = EmployeeAssembler.convert(employeeService
				.loadAll(new PageParam(0, 0, " department.path like ? ",
						params, " employeeCode asc ")).rows);

		return result;
	}
}
